﻿package baseEngine.core
{
    import flash.geom.*;

    final public class Poly3D extends Object
    {
        public var v0:Vector3D;
        public var v1:Vector3D;
        public var v2:Vector3D;
        public var uv0:Point;
        public var uv1:Point;
        public var uv2:Point;
        public var normal:Vector3D;
        public var plane:Number;
        private var _axis:Number;
        private var _tu1:Number;
        private var _tv1:Number;
        private var _tu2:Number;
        private var _tv2:Number;
        private var _tu0:Number;
        private var _tv0:Number;
        private var _alpha:Number;
        private var _beta:Number;
        private static var _a:Vector3D = new Vector3D();
        private static var _b:Vector3D = new Vector3D();
        private static var c:Vector3D = new Vector3D();
        private static var V:Vector3D = new Vector3D();
        private static var Rab:Vector3D = new Vector3D();
        private static var Rbc:Vector3D = new Vector3D();
        private static var Rca:Vector3D = new Vector3D();
        private static var sub:Vector3D = new Vector3D();

        public function Poly3D(param1:Vector3D, param2:Vector3D, param3:Vector3D, param4:Point = null, param5:Point = null, param6:Point = null)
        {
            this.v0 = param1;
            this.v1 = param2;
            this.v2 = param3;
            this.uv0 = param4;
            this.uv1 = param5;
            this.uv2 = param6;
            this.normal = new Vector3D();
            this.update();
            return;
        }// end function

        public function update() : void
        {
            _a.x = this.v1.x - this.v0.x;
            _a.y = this.v1.y - this.v0.y;
            _a.z = this.v1.z - this.v0.z;
            _b.x = this.v2.x - this.v0.x;
            _b.y = this.v2.y - this.v0.y;
            _b.z = this.v2.z - this.v0.z;
            this.normal.x = _b.y * _a.z - _b.z * _a.y;
            this.normal.y = _b.z * _a.x - _b.x * _a.z;
            this.normal.z = _b.x * _a.y - _b.y * _a.x;
            this.normal.normalize();
            this.normal.w = -this.normal.dotProduct(this.v0);
            var _loc_1:* = this.normal.x > 0 ? (this.normal.x) : (-this.normal.x);
            var _loc_2:* = this.normal.y > 0 ? (this.normal.y) : (-this.normal.y);
            var _loc_3:* = this.normal.z > 0 ? (this.normal.z) : (-this.normal.z);
            var _loc_4:* = _loc_1 > _loc_2 ? (_loc_1 > _loc_3 ? (_loc_1) : (_loc_3)) : (_loc_2 > _loc_3 ? (_loc_2) : (_loc_3));
            if (_loc_1 == _loc_4)
            {
                this._tu1 = this.v1.y - this.v0.y;
                this._tv1 = this.v1.z - this.v0.z;
                this._tu2 = this.v2.y - this.v0.y;
                this._tv2 = this.v2.z - this.v0.z;
                this._axis = 0;
            }
            else if (_loc_2 == _loc_4)
            {
                this._tu1 = this.v1.x - this.v0.x;
                this._tv1 = this.v1.z - this.v0.z;
                this._tu2 = this.v2.x - this.v0.x;
                this._tv2 = this.v2.z - this.v0.z;
                this._axis = 1;
            }
            else
            {
                this._tu1 = this.v1.x - this.v0.x;
                this._tv1 = this.v1.y - this.v0.y;
                this._tu2 = this.v2.x - this.v0.x;
                this._tv2 = this.v2.y - this.v0.y;
                this._axis = 2;
            }
            this.plane = -this.normal.dotProduct(this.v0);
            return;
        }// end function

        public function isPoint(param1:Number, param2:Number, param3:Number) : Boolean
        {
            if (this._axis == 0)
            {
                this._tu0 = param2 - this.v0.y;
                this._tv0 = param3 - this.v0.z;
            }
            else if (this._axis == 1)
            {
                this._tu0 = param1 - this.v0.x;
                this._tv0 = param3 - this.v0.z;
            }
            else
            {
                this._tu0 = param1 - this.v0.x;
                this._tv0 = param2 - this.v0.y;
            }
            if (this._tu1 != 0)
            {
                this._beta = (this._tv0 * this._tu1 - this._tu0 * this._tv1) / (this._tv2 * this._tu1 - this._tu2 * this._tv1);
                if (this._beta >= 0 && this._beta <= 1)
                {
                    this._alpha = (this._tu0 - this._beta * this._tu2) / this._tu1;
                }
            }
            else
            {
                this._beta = this._tu0 / this._tu2;
                if (this._beta >= 0 && this._beta <= 1)
                {
                    this._alpha = (this._tv0 - this._beta * this._tv2) / this._tv1;
                }
            }
            if (this._alpha >= 0 && this._beta >= 0 && this._alpha + this._beta <= 1)
            {
                return true;
            }
            return false;
        }// end function

        private function closetPointOnLine(param1:Vector3D, param2:Vector3D, param3:Vector3D, param4:Vector3D) : void
        {
            c.x = param3.x - param1.x;
            c.y = param3.y - param1.y;
            c.z = param3.z - param1.z;
            V.x = param2.x - param1.x;
            V.y = param2.y - param1.y;
            V.z = param2.z - param1.z;
            var _loc_5:* = V.length;
            V.normalize();
            var _loc_6:* = V.dotProduct(c);
            if (_loc_6 < 0)
            {
                param4.x = param1.x;
                param4.y = param1.y;
                param4.z = param1.z;
                return;
            }
            if (_loc_6 > _loc_5)
            {
                param4.x = param2.x;
                param4.y = param2.y;
                param4.z = param2.z;
                return;
            }
            V.x = V.x * _loc_6;
            V.y = V.y * _loc_6;
            V.z = V.z * _loc_6;
            param4.x = param1.x + V.x;
            param4.y = param1.y + V.y;
            param4.z = param1.z + V.z;
            return;
        }// end function

        public function closetPoint(param1:Vector3D, param2:Vector3D) : void
        {
            this.closetPointOnLine(this.v0, this.v1, param1, Rab);
            this.closetPointOnLine(this.v1, this.v2, param1, Rbc);
            this.closetPointOnLine(this.v2, this.v0, param1, Rca);
            sub.x = param1.x - Rab.x;
            sub.y = param1.y - Rab.y;
            sub.z = param1.z - Rab.z;
            var _loc_3:* = sub.length;
            sub.x = param1.x - Rbc.x;
            sub.y = param1.y - Rbc.y;
            sub.z = param1.z - Rbc.z;
            var _loc_4:* = sub.length;
            sub.x = param1.x - Rca.x;
            sub.y = param1.y - Rca.y;
            sub.z = param1.z - Rca.z;
            var _loc_5:* = sub.length;
            var _loc_6:* = _loc_3;
            param2.x = Rab.x;
            param2.y = Rab.y;
            param2.z = Rab.z;
            if (_loc_4 <= _loc_6)
            {
                _loc_6 = _loc_4;
                param2.x = Rbc.x;
                param2.y = Rbc.y;
                param2.z = Rbc.z;
            }
            if (_loc_5 < _loc_6)
            {
                param2.x = Rca.x;
                param2.y = Rca.y;
                param2.z = Rca.z;
            }
            return;
        }// end function

        public function getPointU() : Number
        {
            if (!this.uv0)
            {
                return 0;
            }
            var _loc_1:* = (this.uv1.x - this.uv0.x) * this._alpha + (this.uv2.x - this.uv0.x) * this._beta + this.uv0.x;
            return _loc_1 > 0 ? (_loc_1 - int(_loc_1)) : (_loc_1 - int(_loc_1) + 1);
        }// end function

        public function getPointV() : Number
        {
            if (!this.uv0)
            {
                return 0;
            }
            var _loc_1:* = (this.uv1.y - this.uv0.y) * this._alpha + (this.uv2.y - this.uv0.y) * this._beta + this.uv0.y;
            return _loc_1 > 0 ? (_loc_1 - int(_loc_1)) : (_loc_1 - int(_loc_1) + 1);
        }// end function

    }
}
